/***************************************************************************************************************
 *   Author : Manu Joseph
 *   Date : 05/05/2010
 *   Description : A tool that easily allow users to share folders and set permissions
 *   File Name : EasyShareForm.cs
 *   Purpose : Main form of the application
****************************************************************************************************************/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Data.OleDb;
using System.Diagnostics;
using System.Threading;

namespace EasyShare
{
    public partial class EasyShareForm : Form
    {
        // Delegates declarations
        private delegate void ShowStatusMessageDelegate(string message, bool isError);
        private delegate bool Func<T1, T2, T3, T4, T5, T6>(T1 p1, T2 p2, T3 p3, T4 p4, ref T5 p5, ref T6 p6);
        private delegate bool Func<T1>(T1 p1);
        private delegate bool Func<T1,T2,T3>(T1 p1,T2 p2, ref T3 p3);
        private delegate void SetShareNamesDelegate(string[] shareNames);
        private delegate void SetRemoveButtonStateDelegate(bool isEnabled);
        private delegate void SetShareTextDelegate(string name);

        #region Private Instance Members

        private ContactManager m_objContactManager = new ContactManager();

        // For managing share information
        private Dictionary<string, User[]> m_userAssociationTable = new Dictionary<string, User[]>();

        #endregion

        #region Constructors

        // Default constructor
        public EasyShareForm()
        {
            InitializeComponent();

            SetLogFilePath();
        }

        // constructor for passing folderpath
        // through command line arguements
        public EasyShareForm(string folderPath)
        {
            InitializeComponent();            
            folderPath = folderPath.Trim('"'); // remove double quotes around the folder path

            // this is important because when this is invoked from explorer context menu
            // the path provided will be shortened by adding ~ symbols
            // share created with this path will not be detected by windows
            // so always expand the path obtained from explorer context menu
            folderPath = Path.GetFullPath(folderPath);

            if (Directory.Exists(folderPath) == true)
            {
                FolderPathTextBox.Text = folderPath; 
            }
            SetLogFilePath();

            SetDisplayPosition();
        }

        // sets the start position of the window so that the form is displayed adjacent
        // to the cursor
        private void SetDisplayPosition()
        {
            this.StartPosition = FormStartPosition.Manual;

            // Calculating the upper-left corner position of the window
            Point startPos = Cursor.Position;
            if ((startPos.X + this.Width) > Screen.PrimaryScreen.WorkingArea.Right)
            {
                // adjusting the x value of start pos
                startPos.X -= (startPos.X + this.Width - Screen.PrimaryScreen.WorkingArea.Right);
            }
            if ((startPos.Y + this.Height) > Screen.PrimaryScreen.WorkingArea.Bottom)
            {
                // adjusting the y value of start pos
                startPos.Y -= (startPos.Y + this.Height - Screen.PrimaryScreen.WorkingArea.Bottom);
            }

            this.Location = startPos;
        }

        #endregion

        #region Private Helper Functions

        private static void SetLogFilePath()
        {
            // Sets the file name of the Default trace listener
            DefaultTraceListener traceFile = new DefaultTraceListener();
            string folderPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            traceFile.LogFileName = folderPath + Path.DirectorySeparatorChar + EasyShareConstants.LOG_FILENAME;
            Trace.Listeners.Add(traceFile);
        }

        // Shows the status message in the status label
        // also invokes this on the ui thread
        private void ShowStatusMessage(string message, bool isError)
        {
            if (statusStrip.InvokeRequired == true)
            {
                statusStrip.Invoke(new ShowStatusMessageDelegate(ShowStatusMessage), message, isError);
            }
            else
            {
                if (isError == false)
                {
                    StatusLabel.ForeColor = Color.Black;
                }
                else
                {
                    StatusLabel.ForeColor = Color.Red;
                }

                StatusLabel.Text = message;
            }
        }

        private void SetContactsGridDataSource(DataTable contactsTable)
        {
            if (ContactsDataGrid.InvokeRequired == true)
            {
                ContactsDataGrid.Invoke(new Action<DataTable>(SetContactsGridDataSource), contactsTable);
            }
            else
            {
                if (ContactsDataGrid.Rows.Count > 0)
                {
                    ContactsDataGrid.Rows.Clear();
                    for (int i = 0; i < contactsTable.Rows.Count; i++)
                    {
                        int index = ContactsDataGrid.Rows.Add();
                        ContactsDataGrid.Rows[index].Cells["NameColumn"].Value = contactsTable.Rows[i]["Name"];
                        ContactsDataGrid.Rows[index].Cells["AliasColumn"].Value = contactsTable.Rows[i]["Alias"];
                    }
                }
            }
        }

        // Loads contacts from the db
        // and fills the datagrid
        private void LoadContacts()
        {
            // Loading the contacts from the database
            // and binding to the datagrid
            DataTable contactsTable = null;
            bool ret = m_objContactManager.GetAllContacts(ref contactsTable);
            if (ret == true)
            {
                SetContactsGridDataSource(contactsTable);
                ShowStatusMessage("Contacts loaded", false);
            }
            else
            {
                ShowStatusMessage("Error occurred while loading the contacts from database", true);
            }
        }

        /// <summary>
        /// Saves the selected users to the Db
        /// </summary>
        private void SaveSelectedContacts()
        {
            // Try n save all the selected contacts
            bool bSuccess = true;
            foreach (DataGridViewRow contact in ContactsDataGrid.SelectedRows)
            {
                if (contact.IsNewRow == false)
                {
                    bool bRet = m_objContactManager.SaveContact(contact.Cells["NameColumn"].Value.ToString().Trim(), contact.Cells["AliasColumn"].Value.ToString().Trim());
                    if (bRet == false)
                    {
                        bSuccess = false;
                    }
                }
            }

            if (bSuccess == true)
            {
                ShowStatusMessage("Contact(s) saved successfully", false);
            }
            else
            {
                ShowStatusMessage("Contact(s) save failed", true);
            }
        }

        private void CheckSelectedContacts()
        {
            // Collecting selected user names
            List<string> usersList = new List<string>();
            foreach (DataGridViewRow userRow in ContactsDataGrid.SelectedRows)
            {
                if (userRow.IsNewRow == false)
                {
                    usersList.Add(userRow.Cells["NameColumn"].Value.ToString().Trim());
                }
            }

            // Checking validity asynchronously
            // this is necessary because wmi query for users
            // is a costly operation
            EasyShareConstants.Func<string[], string[], Dictionary<string, string>, bool> validationDelegate = new EasyShareConstants.Func<string[], string[], Dictionary<string, string>, bool>(Win32ShareWrapper.GetInvalidUsers);
            string[] invalidUsers = null;
            Dictionary<string, string> userMap = null;
            IAsyncResult token = validationDelegate.BeginInvoke(usersList.ToArray(), ref invalidUsers, ref userMap,  null, null);

            // Displaying the wait form
            WaitForm objWaitForm = new WaitForm(token, "Operation in Progress", "Searching for users..");
            objWaitForm.ShowDialog();

            // retrieving the result
            bool ret = validationDelegate.EndInvoke(ref invalidUsers, ref userMap, token);

            // Checking the users
            if (ret == true)
            {
                if (invalidUsers.Length > 0)
                {
                    // Constructing comma separated list of invalid users
                    StringBuilder invalidUserString = new StringBuilder();
                    for (int i = 0; i < invalidUsers.Length; i++)
                    {
                        invalidUserString.Append(invalidUsers[i]);
                        invalidUserString.Append(',');
                    }
                    if (invalidUserString.Length > 0)
                    {
                        invalidUserString.Remove(invalidUserString.Length - 1, 1);
                    }

                    ShowStatusMessage("Username(s) - (" + invalidUserString.ToString() + ") are not valid", true);
                    MessageBox.Show("Username(s) - (" + invalidUserString.ToString() + ") are not valid." + Environment.NewLine + Environment.NewLine
                        + " Please enter usernames in the format '<domain_name>\\<user_name>'", EasyShareConstants.TOOL_NAME,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    ShowStatusMessage("All user names are valid", false);
                    MessageBox.Show("All selected user names are valid", EasyShareConstants.TOOL_NAME,
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else
            {
                ShowStatusMessage("Error occurred while searching for users", true);
            }
        }

        private void IncrementShareCountOfUsers(object users)
        {
            m_objContactManager.IncrementShareCount((User[])users);
        }

        // iterates the datagridview and contructs list of selected users
        // along with permissions assigned
        // throws ArgumentException if any of the usernames are empty or null
        private List<User> GetUsersList()
        {
            List<User> usersList = new List<User>();

            foreach (DataGridViewRow userRow in ContactsDataGrid.Rows)
            {
                if (userRow.IsNewRow == false)
                {
                    if ((userRow.Cells["SelectColumn"].Value != null) &&
                        (Boolean.Parse(((DataGridViewCheckBoxCell)userRow.Cells["SelectColumn"]).Value.ToString()) == true))
                    {
                        if ((userRow.Cells["NameColumn"].Value != null) &&
                            (userRow.Cells["NameColumn"].Value.ToString().Trim() != string.Empty))
                        {
                            User user = new User();
                            user.UserName = userRow.Cells["NameColumn"].Value.ToString().Trim();
                            if ((userRow.Cells["ReadColumn"].Value != null) &&
                                (Boolean.Parse(((DataGridViewCheckBoxCell)userRow.Cells["ReadColumn"]).Value.ToString()) == true))
                            {
                                user.AllowRead = true;
                            }
                            else
                            {
                                user.AllowRead = false;
                            }
                            if ((userRow.Cells["FullControlColumn"].Value != null) &&
                                (Boolean.Parse(((DataGridViewCheckBoxCell)userRow.Cells["FullControlColumn"]).Value.ToString()) == true))
                            {
                                user.AllowFullControl = true;
                            }
                            else
                            {
                                user.AllowFullControl = false;
                            }

                            usersList.Add(user);
                        }
                        else
                        {
                            throw new ArgumentException("User name cannot be empty");
                        }
                    }
                }
            }
            return usersList;
        }

        // generates the warning message string
        private string GetWarningMessage(string[] warnings)
        {
            StringBuilder warningMsg = new StringBuilder();
            for (int i = 0; i < warnings.Length; i++)
            {
                warningMsg.Append(i + 1);
                warningMsg.Append(". ");
                warningMsg.Append(warnings[i]);
                warningMsg.Append(Environment.NewLine);
            }
            return warningMsg.ToString();
        }

        // loads the share names available at the given location
        // and displays them in the share names combo box
        private void LoadShareNames(object path)
        {
            Share[] shareNames = Win32ShareWrapper.GetAllShareNames((string)path);

            // storing the user association information for future use
            m_userAssociationTable.Clear();
            string[] arrShareNames = new string[shareNames.Length];
            for (int i = 0; i < shareNames.Length; i++)
            {
                arrShareNames[i] = shareNames[i].ShareName;
                m_userAssociationTable.Add(shareNames[i].ShareName, shareNames[i].UsersList.ToArray());
            }

            if (shareNames.Length > 0)
            {
                SetShareNames(arrShareNames);
                // SetRemoveButtonState(true); 
            }
            else
            {
                SetShareText(Path.GetFileName((string)path));
                // SetRemoveButtonState(false);
            }

            ShowStatusMessage("Share information loaded", false);
        }

        private void SetShareText(string name)
        {
            if (ShareNamesCombobox.InvokeRequired == false)
            {
                ShareNamesCombobox.Items.Clear();
                ShareNamesCombobox.Text = name;
            }
            else
            {
                ShareNamesCombobox.Invoke(new SetShareTextDelegate(SetShareText), name);
            }
        }

        private void SetShareNames(string[] shareNames)
        {
            if (ShareNamesCombobox.InvokeRequired == false)
            {
                ShareNamesCombobox.Items.Clear();
                ShareNamesCombobox.Items.AddRange(shareNames);
                if (ShareNamesCombobox.Items.Count > 0)
                {
                    ShareNamesCombobox.SelectedIndex = 0;
                }
            }
            else
            {                
                ShareNamesCombobox.Invoke(new SetShareNamesDelegate(SetShareNames), new object[] { shareNames });
            }
        }

        private void SetRemoveButtonState(bool isEnabled)
        {
            if (RemoveButton.InvokeRequired == false)
            {
                RemoveButton.Enabled = isEnabled;
            }
            else
            {
                SetRemoveButtonStateDelegate objSRBSDelegate = new SetRemoveButtonStateDelegate(SetRemoveButtonState);
                RemoveButton.Invoke(objSRBSDelegate, isEnabled);
            }
        }

        private void MarkAssociatedUsers(User[] userList)
        {
            // If a user is in the list mark him -- with appropriate permission
            // else add him as new row
            ContactsDataGrid.SuspendLayout();

            // clear all select check boxes
            foreach (DataGridViewRow userRow in ContactsDataGrid.Rows)
            {
                ((DataGridViewCheckBoxCell)userRow.Cells["SelectColumn"]).Value = false;
            }

            for (int i = 0; i < userList.Length; i++)
            {
                bool bFound = false;
                foreach (DataGridViewRow userRow in ContactsDataGrid.Rows)
                {
                    if ((userRow.Cells["NameColumn"].Value != null) &&
                            (userRow.Cells["NameColumn"].Value.ToString().Trim().ToUpper() == userList[i].UserName.ToUpper())) // comparison should be case insensitive
                    {
                        ((DataGridViewCheckBoxCell)userRow.Cells["SelectColumn"]).Value = true;
                        ((DataGridViewCheckBoxCell)userRow.Cells["FullControlColumn"]).Value = userList[i].AllowFullControl;
                        ((DataGridViewCheckBoxCell)userRow.Cells["ReadColumn"]).Value = userList[i].AllowRead;

                        bFound = true;
                        break;
                    }
                }

                if (bFound == false)
                {
                    // not found add as new row
                    int index = ContactsDataGrid.Rows.Add();
                    ContactsDataGrid.Rows[index].Cells["NameColumn"].Value = userList[i].UserName;
                    ((DataGridViewCheckBoxCell)ContactsDataGrid.Rows[index].Cells["SelectColumn"]).Value = true;
                    ((DataGridViewCheckBoxCell)ContactsDataGrid.Rows[index].Cells["FullControlColumn"]).Value = userList[i].AllowFullControl;
                    ((DataGridViewCheckBoxCell)ContactsDataGrid.Rows[index].Cells["ReadColumn"]).Value = userList[i].AllowRead;
                }
            }

            ContactsDataGrid.ResumeLayout(true);
        }

        // Sets the share button label and remove button state
        // according to whether share is already present or not
        private void SetShareState()
        {
            string shareName = ShareNamesCombobox.Text;
            if (m_userAssociationTable.ContainsKey(shareName) == true)
            {
                ShareButton.Text = "Modify";
                RemoveButton.Enabled = true;
            }
            else
            {
                ShareButton.Text = "Share";
                RemoveButton.Enabled = false;
            }
        }

        // modifies the users list of an existing share
        private void ModifyShare(string shareName, List<User> usersList)
        {
            // Invoking begin create share asyncronouly
            string[] warnings = null;
            Func<string, User[], string[]> modifyDelegate = new Func<string, User[], string[]>(Win32ShareWrapper.AssignPermissionsToUsers);
            IAsyncResult waitHandle = modifyDelegate.BeginInvoke(shareName, usersList.ToArray(), ref warnings, null, null);

            // Displaying the wait form
            WaitForm waitForm = new WaitForm(waitHandle, "Operation in Progress", "Modifying share permissions...");
            waitForm.ShowDialog();

            // Displaying result to the user
            bool result = modifyDelegate.EndInvoke(ref warnings, waitHandle);
            if (result == true)
            {
                // Share created successfully -- increment share count also
                System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(IncrementShareCountOfUsers), usersList.ToArray());
                ShareUNCPathTextBox.Text = String.Format(@"\\{0}\{1}", System.Environment.MachineName, shareName);

                if (warnings.Length == 0) // check if any warnings were generated
                {
                    ShowStatusMessage("Share modified successfully", false);
                    MessageBox.Show("Share modified successfully", EasyShareConstants.TOOL_NAME, MessageBoxButtons.OK,
                        MessageBoxIcon.Asterisk);
                }
                else
                {
                    ShowStatusMessage("Share modified with warnings", false);
                    DialogResult dr = MessageBox.Show("Share modified with warnings. Do you wish to see the warnings generated?",
                        EasyShareConstants.TOOL_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    if (dr == DialogResult.Yes)
                    {
                        string warningMessage = GetWarningMessage(warnings);
                        MessageBox.Show(warningMessage, EasyShareConstants.TOOL_NAME + " - Warnings", MessageBoxButtons.OK,
                            MessageBoxIcon.None);
                    }
                }

                if (m_userAssociationTable.ContainsKey(shareName) == true)
                {
                    m_userAssociationTable[shareName] = usersList.ToArray();
                }
                SetShareState();
            }
            else
            {
                ShowStatusMessage("Share modification failed", true);
                MessageBox.Show("Share modification failed", EasyShareConstants.TOOL_NAME, MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        // creates a new share
        private void CreateShare(string folderPath, string shareName, List<User> usersList)
        {
            // Invoking begin create share asyncronouly
            string[] warnings = null;
            string uncPath = null;
            Func<string, string, string, User[], string, string[]> createDelegate = new Func<string, string, string, User[], string, string[]>(Win32ShareWrapper.CreateDirectoryShare);
            IAsyncResult waitHandle = createDelegate.BeginInvoke(folderPath, shareName, ShareDescriptionTextBox.Text.Trim(), usersList.ToArray(), ref uncPath, ref warnings, null, null);

            // Displaying the wait form
            WaitForm waitForm = new WaitForm(waitHandle, "Operation in Progress", "Creating share and setting permissions...");
            waitForm.ShowDialog();

            // Displaying result to the user
            bool result = createDelegate.EndInvoke(ref uncPath, ref warnings, waitHandle);
            if (result == true)
            {
                // Share created successfully -- increment share count also
                System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(IncrementShareCountOfUsers), usersList.ToArray());
                ShareUNCPathTextBox.Text = uncPath; // show the unc path returned for easy copying

                if (warnings.Length == 0) // check if any warnings were generated
                {
                    ShowStatusMessage("Share successfully created", false);
                    MessageBox.Show("Share successfully created", EasyShareConstants.TOOL_NAME, MessageBoxButtons.OK,
                        MessageBoxIcon.Asterisk);
                }
                else
                {
                    ShowStatusMessage("Share created with warnings", false);
                    DialogResult dr = MessageBox.Show("Share created with warnings. Do you wish to see the warnings generated?",
                        EasyShareConstants.TOOL_NAME, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                    if (dr == DialogResult.Yes)
                    {
                        string warningMessage = GetWarningMessage(warnings);
                        MessageBox.Show(warningMessage, EasyShareConstants.TOOL_NAME + " - Warnings", MessageBoxButtons.OK,
                            MessageBoxIcon.None);
                    }
                }

                ShareNamesCombobox.Items.Add(shareName);
                m_userAssociationTable.Add(shareName, usersList.ToArray());
                ShareNamesCombobox.SelectedItem = shareName;
                SetShareState();
            }
            else
            {
                ShowStatusMessage("Share creation failed", true);
                MessageBox.Show("Share creation failed", EasyShareConstants.TOOL_NAME, MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        #endregion

        private void EasyShareForm_Load(object sender, EventArgs e)
        {
            // Start loading contacts from the db
            ContactsLoadWorkerThread.RunWorkerAsync();
        }

        // folder browser for selecting folder to be shared
        private void FolderBrowseButton_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog objFolderBrowser = new FolderBrowserDialog();
            objFolderBrowser.Description = "Select the folder which you want to share..";
            objFolderBrowser.ShowNewFolderButton = true;

            if (Directory.Exists(FolderPathTextBox.Text.Trim()) == true)
            {
                objFolderBrowser.SelectedPath = FolderPathTextBox.Text.Trim();
            }

            if (objFolderBrowser.ShowDialog() == DialogResult.OK)
            {
                FolderPathTextBox.Text = objFolderBrowser.SelectedPath;
            }
        }                      

        //
        // Creates the directory share with appropriate permissions
        //
        private void ShareButton_Click(object sender, EventArgs e)
        {
            bool isNew = true; // indicates whether share is a new share or not

            string folderPath = FolderPathTextBox.Text.Trim();
            string shareName = ShareNamesCombobox.Text.Trim();

            // Performing validations
            // checking share path
            if (folderPath == string.Empty)
            {
                MessageBox.Show("Please enter the path of the folder to be shared", EasyShareConstants.TOOL_NAME,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            else
            {
                if (Directory.Exists(folderPath) == false)
                {
                    MessageBox.Show("Please enter a valid path for the folder to be shared", EasyShareConstants.TOOL_NAME,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }

            // checking share name
            if (shareName == string.Empty)
            {
                MessageBox.Show("Please enter a share name", EasyShareConstants.TOOL_NAME,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            else
            {
                if (Win32ShareWrapper.IsShareNameAvailable(shareName) == false)
                {
                    isNew = false;
                    
                    // specified share name is already being used
                    // check if it is being used for the same path -- if yes modify the share
                    // if no then this raise an error and return
                    if (Win32ShareWrapper.IsShareNameAvailableAtPath(shareName, folderPath) == false)
                    {
                        MessageBox.Show("Specified share name is already being used for sharing another folder. Please choose a different share name", EasyShareConstants.TOOL_NAME,
                                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }
            }
            // END -- Performing validations
            
            // constructing the users array
            List<User> usersList;
            try
            {
                usersList = GetUsersList();
            }
            catch (ArgumentException ex)
            {
                Trace.WriteLine("User name selected was empty : " + ex.ToString());
                MessageBox.Show("Please enter usernames for all selected contacts", EasyShareConstants.TOOL_NAME,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // show warning if no users are selected
            if (usersList.Count == 0)
            {
                DialogResult dr = MessageBox.Show("No users are selected for association. Share will be created with default privileges. OK?",
                    EasyShareConstants.TOOL_NAME, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
                if (dr == DialogResult.Cancel)
                {
                    return;
                }
            }

            if (isNew == true)
            {
                CreateShare(folderPath, shareName, usersList);
            }
            else
            {
                ModifyShare(shareName, usersList);
            }
        }        

        // Removes the specified share
        private void RemoveButton_Click(object sender, EventArgs e)
        {
            string folderPath = FolderPathTextBox.Text.Trim();
            string shareName = ShareNamesCombobox.Text.Trim();

            // Performing validations
            // checking share path
            if (folderPath == string.Empty)
            {
                MessageBox.Show("Please enter the local path of the share to be deleted", EasyShareConstants.TOOL_NAME,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            else
            {
                if (Directory.Exists(folderPath) == false)
                {
                    MessageBox.Show("Please enter a valid local path of the share to be deleted", EasyShareConstants.TOOL_NAME,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }

            // checking share name
            if (shareName == string.Empty)
            {
                MessageBox.Show("Please enter the name of share to be deleted", EasyShareConstants.TOOL_NAME,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            else
            {
                if (Win32ShareWrapper.IsShareNameAvailableAtPath(shareName, folderPath) == false)
                {
                    MessageBox.Show("Specified share name is not present on the given local path. Cannot delete share", EasyShareConstants.TOOL_NAME,
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            // END -- Performing validations

            Func<string> deleteDelegate = new Func<string>(Win32ShareWrapper.RemoveShare);
            IAsyncResult waitHandle = deleteDelegate.BeginInvoke(shareName, null, null);

            // Displaying the wait form
            WaitForm waitForm = new WaitForm(waitHandle, "Operation in Progress", "Deleting share...");
            waitForm.ShowDialog();

            // Displaying result to the user
            bool result = deleteDelegate.EndInvoke(waitHandle);
            if (result == true)
            {
                ShareUNCPathTextBox.Text = string.Empty;
                
                ShowStatusMessage("Share successfully deleted", false);
                MessageBox.Show("Share successfully deleted", EasyShareConstants.TOOL_NAME, MessageBoxButtons.OK,
                    MessageBoxIcon.Asterisk);

                ShareNamesCombobox.Items.Remove(shareName);
                m_userAssociationTable.Remove(shareName);
                if (ShareNamesCombobox.Items.Count > 0)
                {
                    ShareNamesCombobox.SelectedIndex = 0;                    
                }
                else
                {
                    ShareNamesCombobox.Text = Path.GetFileName(folderPath);                    
                }
                SetShareState();                
            }
            else
            {
                ShowStatusMessage("Share deletion failed", false);
                MessageBox.Show("Share deletion failed", EasyShareConstants.TOOL_NAME, MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        // This connects to the contacts database and loads the existing contacts
        private void ContactsLoadWorkerThread_LoadContacts(object sender, DoWorkEventArgs e)
        {
            ShowStatusMessage("Loading contacts...", false);

            LoadContacts();       
        }        

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;

            SaveSelectedContacts();

            this.Cursor = Cursors.Default;
        }        

        // Reloads the contacts from the db
        // if another reload is not already in progress
        private void ReloadContactsLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (ContactsLoadWorkerThread.IsBusy == false)
            {
                ContactsLoadWorkerThread.RunWorkerAsync();
            }
        }

        private void ContactsDataGrid_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
            // set the value of read column as checked by default
            for (int i = 0; i < e.RowCount; i++)
            {
                ContactsDataGrid.Rows[e.RowIndex + i].Cells["ReadColumn"].Value = true;
            }
        }

        private void checkContactsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            
            CheckSelectedContacts();

            this.Cursor = Cursors.Default;
        }        

        // showing the about box
        private void AboutLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            EasyShareAboutBox aboutBox = new EasyShareAboutBox();
            aboutBox.ShowDialog();
        }

        // Displays the form for managing contacts
        private void ManageContactsLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ManageContactsForm manageForm = new ManageContactsForm(m_objContactManager);
            manageForm.ShowDialog();
        }        

        private void ShareNameTextBox_TextChanged(object sender, EventArgs e)
        {
            ShareUNCPathTextBox.Text = string.Empty;
        }

        private void CopySharePathToClipboardLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            string sharePath = ShareUNCPathTextBox.Text;
            if ((sharePath != null) && (sharePath != string.Empty))
            {
                // copy the share path to clipboard
                Clipboard.SetText(ShareUNCPathTextBox.Text, TextDataFormat.UnicodeText); 
            }
        }

        private void ShareUNCPathTextBox_TextChanged(object sender, EventArgs e)
        {
            CopySharePathToClipboardLinkLabel.Enabled = ((ShareUNCPathTextBox.Text != null) 
                                                            && (ShareUNCPathTextBox.Text != string.Empty));                      
        }

        private void EasyShareForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                e.Handled = true;
                this.Close();
            }
        }
        
        private void FolderPathTextBox_TextChanged(object sender, EventArgs e)
        {
            if (Directory.Exists(FolderPathTextBox.Text.Trim()) == true)
            {
                ShowStatusMessage("Loading share information...", false);
                
                // background worker changed to threadpool to avoid conflicts
                // LoadSharesBackgroundWorker.RunWorkerAsync();
                ThreadPool.QueueUserWorkItem(new WaitCallback(LoadShareNames), FolderPathTextBox.Text.Trim());
            }
        }

        private void LoadSharesBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            LoadShareNames(FolderPathTextBox.Text.Trim());           
        }        

        private void ShareNamesCombobox_TextChanged(object sender, EventArgs e)
        {            
            SetShareState();

            // if the newly selected item is in the list of know shares
            // mark the associated users
            string shareName = ShareNamesCombobox.Text;
            if (m_userAssociationTable.ContainsKey(shareName) == true)
            {
                MarkAssociatedUsers(m_userAssociationTable[shareName]);
            }

            // ShareUNCPathTextBox.Text = string.Empty; // clearing the unc path text box
        }              
    }
}